#include <iostream>
using namespace std;
#include <cstring>

#define BUFFER_SIZE 100

class Person
{
public: //公有的
    Person(); // 无参构造函数

    Person(int age, char sex, const char *name); // 有参构造函数

    Person(const Person &obj); // 拷贝构造函数

    ~Person(); // 析构函数
public: 
    void setAge(int age);
    void setSex(char sex);
    void setName(const char *name);

    int getAge();
    char getSex();
    char *getName();

protected:  //受保护的
    int m_test;

private: // 私有的
    int m_age;
    char m_sex;
    char *m_name;
    // const char bloodType; // 血型
};

/*析构函数 : 对象的声明周期结束的时候*/
Person::Person() // 无参构造函数
{
    cout << "我是无参构造函数" << endl;
    m_name = new char[BUFFER_SIZE];
    memset(m_name, 0, sizeof(char) * BUFFER_SIZE);
}

// Person::Person(int age, char sex, const char *name) // 有参构造函数
// {
//     cout << "我是有参构造函数" << endl;
//     m_age = age;
//     m_sex = sex;
//     m_name = new char[BUFFER_SIZE];
//     /* 清理脏数据 */
//     memset(m_name, 0, sizeof(char) * BUFFER_SIZE);
//     strcpy(m_name, name);
// }

/*
    初始化列表
        1.用法:语法
        2.好处:速度快
        3.定要用初始化列表的两个场景:{1.当我们的成员属性被const限定的时候,
                                    2.当类的内部有新的类(c类),且c类有构造函数的时候}
*/
Person::Person(int age, char sex, const char *name) : m_age(age), m_sex(sex), m_name(new char[BUFFER_SIZE])
{

    strcpy(m_name, name);
}

Person::Person(const Person &obj)
{
    cout << "我是拷贝构造" << endl;
    m_age = obj.m_age;
    m_sex = obj.m_sex;
    int length = strlen(obj.m_name);
    m_name = new char[length + 1];
    /*清除脏数据 */
    memset(m_name, 0, sizeof(char) * (length + 1));
    strcpy(m_name, obj.m_name);
}

Person::~Person() // 析构函数(释放内存)  对象的声明周期结束的时候会调用
{
    cout << "我是析构函数" << endl;

    if (m_name != NULL)
    {
        delete[] m_name;
        m_name = NULL;
    }
}

void Person::setAge(int age)
{
    m_age = age;
}

void Person::setSex(char sex)
{
    m_sex = sex;
}

void Person::setName(const char *name)
{
    strcpy(m_name, name);
}

int Person::getAge()
{
    return m_age;
}

char Person::getSex()
{
    return m_sex;
}

char *Person::getName()
{
    return m_name;
}

int main()
{
    /*当我定义一个对象的时候，会默认调用构造函数*/
    // Person per1;    //无参构造
    // per1.setName("zahngsan");
    // cout << "name: " << per1.getName() << endl;

    Person per2(30, 'm', "mr_zhou"); // 有参构造

    cout << "name:" << per2.getName() << endl;
    cout << "sex:" << per2.getSex() << endl;
    cout << "age:" << per2.getAge() << endl;

#if 0 // 拷贝构造

    /*拷贝构造--per3是基于per2创建出来的对象*/
    /*
        1,当类中没有拷贝构造函数的时候,会使用系统给我们提供的拷贝构造函数,默认浅拷贝,
        2,当类中有指针存在的时候,一定需要深拷贝,所以需要程序员自己实现写拷贝构造函数,
    */
    Person per3(per2);
    cout << "name:" << per2.getName() << endl;
    cout << "sex:" << per2.getSex() << endl;
    cout << "age:" << per2.getAge() << endl;
#endif

#if 1 // 拷贝构造的另一种表现方式

    /*拷贝构造的另一种表现方式 */
    Person per4 = per2;
    cout << "per4 name:" << per4.getName() << endl;
    cout << "per4 sex:" << per4.getSex() << endl;
    cout << "per4 age:" << per4.getAge() << endl;
#endif

    return 0;
}